package com.ming.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;

import javax.servlet.ServletRequest;
import java.io.Serializable;

/**
 * 重写 DefaultWebSessionManager 与 CustomSessionManager 一起使用  解决频繁访问 redis。
 * spring-shiro.xml 中，id=sessionManager ,配置 org.apache.shiro.web.session.mgt.DefaultWebSessionManager ,
 * 在 RewriteShiroSessionDao 类的 doReadSession 方法中进行日志输出，查看效果
 * @author MING
 * @date 2018/9/12 12:00
 */
public class CustomSessionManager extends DefaultWebSessionManager {

    /**
     * SessionKey 中储存的有request对象
     * 将 sessionKey 放进request对象中，读取的时候直接从request中读取，这样就可以减少对redis的访问频率
     *
     * @param sessionKey
     * @return
     * @throws UnknownSessionException
     */
    protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
//        通过 sessionKey 获取到 sessionId
        Serializable sessionId = getSessionId(sessionKey);
        ServletRequest request = null;
        if (sessionKey instanceof WebSessionKey) {
//            将 sessionKey 强转成 WebSessionKey
            request = ((WebSessionKey) sessionKey).getServletRequest();
        }
        if (request != null && sessionId != null) {
//            直接从 request 中获取 session
            Session session = (Session) request.getAttribute(sessionId.toString());
            if (session != null) {
                return session;
            }
        }
//        从 redis 中取的 session ；最后会调用RewriteShiroSessionDao中的doReadSession
        Session session = super.retrieveSession(sessionKey);
        if (request != null && sessionId != null) {
//            将取出来的 session 对象放进request对象中
            request.setAttribute(sessionId.toString(), session);
        }
        return session;
    }
}
